/* Teach Tool  - Structural Dynamics
 * Copyright (C) 2009: Fabian Gerold, www.fabiangerold.de
 *
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 3 (the "GPL").
 * 
 * Software distributed under the License is distributed 
 * on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either 
 * express or implied. See the GPL for the specific language 
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this 
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc., 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOption>

#include "SpringDamp.h"

SpringDamp::SpringDamp()
{
	setZValue(1);
	m_w = 15.0;
	m_disp = 0;
	m_disp_old = 0;
	m_ground_disp = 0;
	m_ground_disp_old = 0;
	m_amp = 1;
	m_scale_spring = 0.5;
	m_scale_damp = 0.1;
}

void SpringDamp::setDisp( double disp, double ground_disp )
{
	// determine amplitude
	float fdisp = disp >=0 ? disp : -disp;
	
	if( fdisp > m_amp )
	{
		m_amp = fdisp;
	}
	else if( m_amp_disp > fdisp && m_amp_disp > m_amp_disp_old ) // cap
	{
		//m_amp = m_disp>=0 ? m_disp : -m_disp;
		m_amp = m_amp_disp;
	}
	m_amp_disp_old = m_amp_disp;
	m_amp_disp = fdisp;
	if( m_amp < 0.005 && ground_disp == 0.0 )
		return;

	m_disp_old = m_disp;
	m_disp = disp;
	//m_w = (150.0 + m_disp*100.0)/10.0;
	m_w = (150.0 + (m_disp-ground_disp)*100.0)/10.0;

	m_ground_disp_old = m_ground_disp;
	m_ground_disp = ground_disp;


	update();
}

void SpringDamp::resetDisp()
{
	m_disp = 0;
	m_disp_old = 0;
	m_ground_disp = 0;
	m_ground_disp_old = 0;
	m_amp = 1;
	m_w = 15.0;

	update();
}

void SpringDamp::setSpring( double k )
{
	m_scale_spring = 0.1 + k*0.00002;
	update();
}

void SpringDamp::setDamp( double d )
{
	m_scale_damp = 0.1 + d*0.01;
	if( d == 0.0 )
		m_scale_damp = 0.0;
	update();
}

void SpringDamp::initPos( qreal x, qreal y )
{
	setPos( x, y );
	m_amp = 0;
}

QRectF SpringDamp::boundingRect() const
{
	return QRectF( -30+m_ground_disp_old*100, -75, 270 + m_disp_old*100 + 20, 150 );
}

void SpringDamp::paint( QPainter *painter, const QStyleOptionGraphicsItem*, QWidget* )
{
	//float w = (150.0 + m_disp*100.0)/10.0;
	float ys = m_scale_spring*30;
	float x0 = m_ground_disp*100;

	painter->setRenderHint( QPainter::Antialiasing );
	painter->setPen(Qt::NoPen);
	painter->setBrush( QColor( 151, 165, 186 ) );
	painter->drawRect( -25+x0, -60, 25, 120 );

	const QPointF points[14] = {
   		QPointF( x0, -40 ),
		QPointF( x0+25, -40 ),
		QPointF( x0+25+m_w*0.5, -40+ys ),
		QPointF( x0+25+m_w*1.5, -40-ys ),
		QPointF( x0+25+m_w*2.5, -40+ys ),
		QPointF( x0+25+m_w*3.5, -40-ys ),
		QPointF( x0+25+m_w*4.5, -40+ys ),
		QPointF( x0+25+m_w*5.5, -40-ys ),
		QPointF( x0+25+m_w*6.5, -40+ys ),
		QPointF( x0+25+m_w*7.5, -40-ys ),
		QPointF( x0+25+m_w*8.5, -40+ys ),
		QPointF( x0+25+m_w*9.5, -40-ys ),
		QPointF( x0+25+m_w*10, -40 ),
		QPointF( x0+45+m_w*10, -40 )	
    };
	
	painter->setPen( QPen( Qt::gray, 5*m_scale_spring, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin ) );
	painter->drawPolyline( points, 14 );

	painter->setPen( QPen( QColor( 193, 193, 193 ), 4, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
	painter->drawLine( x0+45+m_w*10, -40, x0+45+m_w*10,  40 );
	painter->drawLine( x0+45+m_w*10, 0, x0+120+m_w*10, 0 );

	// damper
	if( m_scale_damp == 0.0 ) return;
	float yd = m_scale_damp*20;

	painter->setPen( QPen( Qt::gray, 5*m_scale_damp, Qt::SolidLine, Qt::FlatCap, Qt::BevelJoin ) );
	painter->drawLine( x0+0, 40, x0+35+m_w*3, 40 );
	painter->drawLine( x0+35+m_w*3, 40, x0+35+m_w*3, 38-yd*0.9 );
	painter->drawLine( x0+35+m_w*3, 40, x0+35+m_w*3, 43+yd*0.9 );
	
	const QPointF points_d2[4] = {
   		QPointF( x0+15+m_w*3.5, 34-yd ),
		QPointF( x0+25+m_w*6, 34-yd ),
		QPointF( x0+25+m_w*6, 46+yd ),
		QPointF( x0+15+m_w*3.5, 46+yd )
		
	};

	painter->drawPolyline( points_d2, 4 );
	painter->drawLine( x0+25+m_w*6, 40, x0+45+m_w*10, 40 );
}

